package last.fm;

/***
 * @author Ragnvald Fuglestein
 */

import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import com.google.common.collect.ObjectArrays;

import baseStructure.Addon;
import baseStructure.Artist;
import baseStructure.SearchArtist;
import baseStructure.SearchTrack;
import baseStructure.Track;

public class LastFmTrackAddon extends Addon implements Serializable {
	private static final long serialVersionUID = 2232908078160662572L;
	
	public static final String ADDON_NAME = "LastFmTrackAddon";
	
	public LastFmTrackAddon() {
		super(ADDON_NAME);
	}
	
	public boolean checkField(Object fieldname) {
		return checkField(fieldname, ANYVALUE);
	}
	
	public boolean checkField(Object fieldname, Object fieldvalue) {
		if ("lovedby".equals(fieldname)) {
			List<Object> list = listField.get("lovedby");
			
			if (list == null) return false;
			return fieldvalue == ANYVALUE || list.contains(fieldvalue);
		}
		
		return false;
	}
	
	@SuppressWarnings("unchecked")
	private void addMapValue(String key, String name, Object value) { //TODO: Remove?
		HashMap<String, Object> map = (HashMap<String, Object>) valueField.get(key);
		if (map == null) { 
			map = new HashMap<String, Object>();
			valueField.put(key, map);
		}
		map.put(name, value);
	}

	public void addLovedBy(String lovedby) { addListField("lovedby", lovedby); }
	
	public void removeLovedBy(String lovedby) { removeListField("lovedby", lovedby); }
	
	public void addPlayCount(String name, int playcount) { addMapValue("playcount", name, playcount); }
	
	public void setRank(int rank) { valueField.put("rank", rank); }
	public void setDuration(int duration) { valueField.put("duration", duration); }
	public void setArtistMBID(String mbid) { valueField.put("artistmbid", mbid); }
	public void setArtistURL(String url) { valueField.put("artisturl", url); }
	public void setArtistName(String name) { valueField.put("artistname", name); }
	public void setTrackMBID(String mbid) { valueField.put("trackmbid", mbid); }
	public void setTrackURL(String url) { valueField.put("trackurl", url); }
	public void setTrackName(String name) { valueField.put("trackname", name); }
	public void setDownloadURL(String url) { valueField.put("downloadurl", url); }
	
	public SearchTrack toSearch() {
		return new SearchTrack(new SearchArtist((String) valueField.get("artistname")), (String) valueField.get("trackname"));
	}
	
	public Track toTrack() { //TODO FIX
		Track track = new Track((String) valueField.get("trackname"));
		track.addAddon(this);
		return track;
	}
	
	public Artist toArtist() {
		return new Artist((String) valueField.get("artistname"));
	}
	
	public String toString() {
		return valueField.get("artistname") + " - " + valueField.get("trackname");
	}
	
	public void love(String name) {
		addLovedBy(name);
	}
	
	public void unlove(String name) {
		removeLovedBy(name);
	}
	
	/* Last.Fm specific code */
	public static void getUserTopTracks(final String user, final String[] params, final LastFmTrackCallback callback) {
		new LastFmJob(user, params, callback) {
			List<LastFmTrackAddon> list = new ArrayList<>();

			@Override public void prepareRequest() {
				this.method = "user.getTopTracks";
				this.params = ObjectArrays.concat(new String[] { "user=" + user }, params, String.class);
			}

			@Override public boolean processResult() {
				try {
					LastFm.getInstance().parseTracks(result, list);
				} catch (IOException e) {
					e.printStackTrace();
					return false;
				}
				return true;
			}

			@Override public void callback() {
				((LastFmTrackCallback) callback).lastFmTracks(list);
			}
		};
	}

	public static void getUserLovedTracks(final String user, final String[] params, final LastFmTrackCallback callback) {
		new LastFmJob(user, params, callback) {
			List<LastFmTrackAddon> list = new ArrayList<>();

			@Override public void prepareRequest() {
				this.method = "user.getLovedTracks";
				this.params = ObjectArrays.concat(new String[] { "user=" + user }, params, String.class);
			}

			@Override public boolean processResult() {
				try {
					LastFm.getInstance().parseTracks(result, list);
				} catch (IOException e) {
					e.printStackTrace();
					return false;
				}
				for (LastFmTrackAddon track : list) { track.addLovedBy(user); }
				return true;
			}

			@Override public void callback() {
				((LastFmTrackCallback) callback).lastFmTracks(list);
			}
		};
	}
}
